#pragma once

#include "NetServer.h"
#include "ChatUser.h"
#include "ChatRoom.h"

#include <boost/pool/detail/singleton.hpp>
#include <map>

class CommandProc;
class ChatServer : public NetServer<ChatUser>
{
    typedef NetServer<ChatUser> super;
public:
    ChatServer(unsigned short port=0);
    virtual ~ChatServer();

    void Open(unsigned short port, size_t maxUserNum, size_t maxRoomNum);

    CommandProc* GetCommandProc(const char* cmd);

    // ChatUser

    ChatUser* GetUser(const char* nick);
    bool SendUserList(ChatUser& user);
    bool Quit(ChatUser& user);
    bool IsExistUser(size_t index) const {
        AUTO(iter, users_.find(index));
        return (iter != users_.end());
    }

    // ChatRoom
    bool MakeRoom(ChatUser& user, const char* title);
    bool JoinRoom(ChatUser& user, size_t index);
    void ExitRoom() { --nowRoomNum_; }

    ChatRoom* GetEmptyRoom();

    bool SendRoomList(ChatUser& user);

    bool IsValidNick(const char* nick) const;
    bool IsValidTitle(const char* title) const;
    
    bool IsExistRoom(size_t index) const
    {
        if (maxRoomNum_ <= index) {
            return false;
        }
        return !rooms_[index]->IsEmtpy();
    }
    
    bool IsRoomFull() const { 
        return nowRoomNum_ >= maxRoomNum_; 
    }

    ChatRoom* GetRoom(size_t index) {
        if (maxRoomNum_ <= index) {
            return false;
        }
        return rooms_[index].get();
    }

    size_t GetUserCount() const {
        return users_.size();
    }

    size_t GetMaxUserNum() const {
        return maxUserNum_;
    }

    size_t GetRoomCount() const {
        return nowRoomNum_;
    }

    size_t GetMaxRoomNum() const {
        return maxRoomNum_;
    }

protected:
    typedef std::map<size_t, NetSessionPtr> ChatUserList;
    typedef std::map<std::string, CommandProc*> CommandList;
    typedef std::vector<ChatRoomPtr> ChatRoomList;

    virtual void handle_accept(const boost::system::error_code& error);

    void StartUp();
    void CleanUp();

    void StartRooms();

    void RegisterCommands();
    void UnRegisterCommands();

    size_t userIdx_;
    size_t maxUserNum_;
    ChatUserList users_;
    
    size_t maxRoomNum_;
    size_t nowRoomNum_;
    ChatRoomList rooms_;

    CommandList cmds_;
};

typedef boost::details::pool::singleton_default<ChatServer> GlobalChatServer;
#define CHATSVR GlobalChatServer::instance()

